package com.ssk.sh.core.enums.handler;

import java.sql.Array;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

@MappedJdbcTypes(value = JdbcType.ARRAY)
@MappedTypes(List.class)
public class BigIntArrayTypeHandler extends BaseTypeHandler<List<Long>> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<Long> parameter, JdbcType jdbcType) throws SQLException {
        if (parameter == null || parameter.isEmpty()) {
            ps.setNull(i, jdbcType == null ? JdbcType.ARRAY.ordinal() : jdbcType.ordinal());
            return;
        }
        // 将 List<Long> 转换为 PostgreSQL 的 bigint[] 类型
        String arrayString = "{" + parameter.stream()
                .map(Object::toString)
                .collect(Collectors.joining(",")) + "}";
        ps.setArray(i, ps.getConnection().createArrayOf("bigint", parameter.toArray(new Long[0])));
    }

    @Override
    public List<Long> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        Object array = rs.getArray(columnName);
        return getArrayToList(array);
    }

    @Override
    public List<Long> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        Object array = rs.getArray(columnIndex);
        return getArrayToList(array);
    }

    @Override
    public List<Long> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        Object array = cs.getArray(columnIndex);
        return getArrayToList(array);
    }

    private List<Long> getArrayToList(Object array) {
        if (array == null) {
            return null;
        }
        // 将 PostgreSQL 的数组对象转换为 List<Long>
        try {
            return Arrays.stream((Long[]) ((Array) array).getArray())
                    .map(element -> ((Number) element).longValue())
                    .collect(Collectors.toList());

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}